#include "QTFEditor.h"
#include "QTFPanel.h"
#include <QtGui/QPainter>
#include <QtCore/QPoint>
#include <QtGui/QMouseEvent>
#include <QtGui/QPainterPath>
#include <QtGui/QPolygon>
#include <QtGui/QLinearGradient>
#include <QtGui/QSlider>
#include <QtGui/QFileDialog>
#include <QtGui/QPushButton>
#include <QtGui/QMenu>

#include <iostream>

//#include "gsl/gsl_rng.h"
//#include "gsl/gsl_randist.h"

using namespace std;

QTFPanel::QTFPanel(int transferWidth, QWidget *parent)
:QTFAbstractPanel(parent)
{
	this->setSizePolicy(QSizePolicy::MinimumExpanding,QSizePolicy::MinimumExpanding);
	this->setMinimumSize(400,190);
	this->setMouseTracking(true);
	m_pTFEditor = (QTFEditor*)parent;
	m_isLeftClick = false;
	m_isRightClick= false;
	m_ifOnDrawing = false;
	m_ifOnDrawColorTick = false;
	m_clickedTicks = -1;
	m_vertStringNeedUpdate = false;
	m_vertTranSliderRange = 10;
	m_ifCTRLPressed = false;
	m_ifSHIFTPressed = false;
	
	m_buttonSize = QSize(20,20);

	m_backgroundMesh = 1; // dot liine
	m_panelImage = new QImage(rect().width(),rect().height(),QImage::Format_RGB32);
	m_tfResolution = 1024;
	m_tfDrawArray = new float[(int)m_tfResolution];
	for(int x=0;x<m_tfResolution;++x)
		m_tfDrawArray[x] = 0.0f;
	
	m_tfColorTick << TFColorTick(0.0f,Qt::red) << TFColorTick(m_tfResolution,Qt::blue);
	initLayout();
	
	m_settingMenu = new QMenu(this);
	
	QMenu	*backgroundMeshMenu = new QMenu(tr("Background Grid"),this);
	changeBM2NoneAct = new QAction(tr("None"),this);
	changeBM2NoneAct->setCheckable(true);
	connect(changeBM2NoneAct, SIGNAL(triggered()), this, SLOT(changeBM2None()));
	changeBM2DotLineAct = new QAction(tr("Dot Line"),this);
	changeBM2DotLineAct->setCheckable(true);
	connect(changeBM2DotLineAct, SIGNAL(triggered()), this, SLOT(changeBM2DotLine()));
	backgroundMeshMenu->addAction(changeBM2NoneAct);
	backgroundMeshMenu->addAction(changeBM2DotLineAct);
	
	QMenu *transferOptionsMenu = new QMenu(tr("Transfer Options"), this);
	changeCombine2OrAct = new QAction(tr("Use Greater"),this);
	changeCombine2AndAct = new QAction(tr("Additive"), this);
	changeCombine2OrAct->setCheckable(true);
	changeCombine2OrAct->setChecked(true);
	changeCombine2AndAct->setCheckable(true);
	connect(changeCombine2OrAct, SIGNAL(triggered()), this, SLOT(changeCombine2Or()));
	connect(changeCombine2AndAct, SIGNAL(triggered()), this, SLOT(changeCombine2And()));
	transferOptionsMenu->addAction(changeCombine2AndAct);
	transferOptionsMenu->addAction(changeCombine2OrAct);
	
	openFileAct = new QAction(tr("Load Settings"),this);
	saveFileAct = new QAction(tr("Save Settings"),this);
	connect(openFileAct, SIGNAL(triggered()), this, SLOT(openFile()));
	connect(saveFileAct, SIGNAL(triggered()), this, SLOT(saveFile()));

	toggleInstantAct = new QAction(tr("Toggle Instant Updates"),this);
	toggleInstantAct->setCheckable(true);
	connect(toggleInstantAct, SIGNAL(triggered()), this, SLOT(toggleInstant()));
	
	m_settingMenu->addMenu(backgroundMeshMenu);
	m_settingMenu->addMenu(transferOptionsMenu);
	m_settingMenu->addAction(openFileAct);
	m_settingMenu->addAction(saveFileAct);
	m_settingMenu->addAction(toggleInstantAct);
	
	m_gaussianObjectArray.resize(0);
	m_clickedObjectControlBox = -1;
	m_ifOnMovingObjectControlBox = false;
	m_objectControlBoxSide = -1;
	
	m_tfColorMapResoultion = transferWidth;
	m_tfColorMap = new float[m_tfColorMapResoultion*4]; // r,g,b,a - 4 channels
	
	changeBM2DotLine();
	setCollapsable(false);
	m_zeroRangesArray.append(ZeroRange(0,1));
	m_instant = false;
}
QTFPanel::~QTFPanel()
{
	delete [] m_tfDrawArray;
	delete [] m_tfColorMap;
	
	delete m_settingMenu;
}
void QTFPanel::initLayout()
{
	QTFAbstractPanel::initLayout(25,1,25,25);

	m_colorTickHeight	= 15;
	
	if(m_colorTickHeight > m_panelDMargin)
		m_panelDMargin = m_panelDMargin;
	
	m_panelArea		= QRect(m_panelLMargin,m_panelUMargin,m_panelWidth,m_panelHeight); 
	m_colorTickArea	= QRect(m_panelLMargin,m_panelHeight+1,m_panelWidth,m_colorTickHeight);

	m_tfRes2PtFactor	= (float)m_panelWidth/(m_tfResolution - 1);
	m_tfPt2ResFactor	= 1.0f/m_tfRes2PtFactor;
	
	m_vertTranSlider	= new QSlider(Qt::Vertical,this);
	m_vertTranSlider->setGeometry(0,0,m_panelLMargin,m_panelUMargin+(m_panelHeight/2));
//	m_vertTranSlider->setTickPosition(QSlider::TicksRight);
	m_vertTranSlider->setRange(1,m_vertTranSliderRange-1);
//	m_vertTranSlider->setTickInterval(1);
	m_vertTranSlider->setValue((int)m_vertTranSliderRange/2);
	m_vertTranSlider->setTracking(true);
	
	connect(m_vertTranSlider,SIGNAL(valueChanged(int)),this,SLOT(vertTranSliderChange(int)));

	m_functionButton = new QPushButton(tr("F"),this);
	m_functionButton->setGeometry(2,m_panelUMargin+(m_panelHeight/2)+2,m_buttonSize.width(),m_buttonSize.height());
	connect(m_functionButton,SIGNAL(released()),this,SLOT(functionButtonPressed()));
	
	m_settingButton = new QPushButton(tr("S"),this);
	m_settingButton->setGeometry(2,m_panelUMargin+(m_panelHeight/2)+2+m_buttonSize.height()+1,m_buttonSize.width(),m_buttonSize.height());
	connect(m_settingButton,SIGNAL(released()),this,SLOT(settingButtonPressed()));
}
void QTFPanel::realPaintEvent(QPaintEvent *)
{
	QPainter painter(this);
	painter.drawImage(rect(),*m_panelImage);

	// draw drawing lines
	QPen	pen1(Qt::black,1);
	QPen	pen2(Qt::black);
	QPen	pen3(Qt::white,1);
	QPen	pen4(Qt::green,1);
	painter.setPen(pen1);
	QBrush	brush1(QColor(255,255,255,100));
	painter.setBrush(brush1);
	QPainterPath path;
	float xposs = m_panelLMargin;
	float yposs = m_panelUMargin + m_panelHeight - 1;
	path.moveTo(xposs,yposs);
	// draw with transform
	int vertSliderValue = m_vertTranSlider->value();
	float halfHeight = 0.5 * m_panelHeight;
	float lowerPart = (float)vertSliderValue/m_vertTranSliderRange;
	float upperPart = 1.0f - lowerPart;//(float)(10-vertSliderValue)/10.0f;
	
	for(int c=0;c<m_tfResolution;++c)
	{
		xposs = m_panelLMargin + c*m_tfRes2PtFactor;
		float ratio,rHeight;
		if(m_tfDrawArray[c] <= lowerPart)
		{
			ratio = m_tfDrawArray[c]/lowerPart;
			if(ratio > 1.0f) ratio = 1.0f;
			rHeight = ratio * halfHeight;
		}
		else
		{
			ratio = (m_tfDrawArray[c] - lowerPart) / upperPart;
			if(ratio > 1.0f) ratio = 1.0f;
			rHeight = halfHeight * (1.0f+ratio); //ratio * 0.5 * m_panelHeight + 0.5 * m_panelHeight
		}
		yposs = m_panelUMargin + m_panelHeight - rHeight - 1;
		path.lineTo(xposs,yposs);
	}
	path.lineTo(rect().width()-m_panelRMargin,m_panelUMargin + m_panelHeight);
	painter.drawPath(path);	

	// draw objects
	if(m_gaussianObjectArray.size() != 0)
	{
		for(int x=0;x<m_gaussianObjectArray.size();++x)
		{
			QPainterPath pathObj;
			xposs = m_panelLMargin;
			yposs = m_panelUMargin + m_panelHeight - 1;
			pathObj.moveTo(xposs,yposs);
			for(int c=0;c<m_tfResolution;++c)
			{
				xposs = m_panelLMargin + c*m_tfRes2PtFactor;
				float ratio,rHeight;
				if(m_gaussianObjectArray[x].m_distribution[c] <= lowerPart)
				{
					ratio = m_gaussianObjectArray[x].m_distribution[c]/lowerPart;
					if(ratio > 1.0f) ratio = 1.0f;
					rHeight = ratio * halfHeight;
				}
				else
				{
					ratio = (m_gaussianObjectArray[x].m_distribution[c] - lowerPart) / upperPart;
					if(ratio > 1.0f) ratio = 1.0f;
					rHeight = halfHeight * (1.0f+ratio); //ratio * 0.5 * m_panelHeight + 0.5 * m_panelHeight
				}
				yposs = m_panelUMargin + m_panelHeight - rHeight - 1;
				pathObj.lineTo(xposs,yposs);
			}
			pathObj.lineTo(rect().width()-m_panelRMargin,m_panelUMargin + m_panelHeight-1);
			painter.drawPath(pathObj);	
		}
	}

	// draw background grid
	if(m_backgroundMesh == 1) // mesh
	{
		QPen	penG(Qt::gray,1);
		penG.setStyle(Qt::DashLine);
		QPen	penW(Qt::white,1);
		penW.setStyle(Qt::DashLine);	
		painter.setPen(penG);
		
		QPointF	px1,px2,py1,py2;
		float gridYheight;
		for(int x=1;x<=9;x=x+1)
		{
			//		px1 = QPointF(m_panelLMargin + ((float)m_panelWidth/10.0f) * x,m_panelUMargin);
			//		px2 = QPointF(m_panelLMargin + ((float)m_panelWidth/10.0f) * x,m_panelUMargin+m_panelHeight);
			//		painter.drawLine(px1,px2);
			if(x == 5)
				painter.setPen(penW);
			else 
				painter.setPen(penG);
			
			if(x <= vertSliderValue)
			{
				gridYheight = m_panelUMargin+m_panelHeight-((float)x/vertSliderValue) * halfHeight;
			}
			else
			{
				int upp = m_vertTranSliderRange - vertSliderValue;
				gridYheight = m_panelUMargin+m_panelHeight-halfHeight-((float)(x-vertSliderValue)/upp) * halfHeight;
			}
			//py2 = QPointF(rect().width()-m_panelRMargin,m_panelUMargin+((float)m_panelHeight/10.0f) * x);
			py1 = QPointF(m_panelLMargin+1,gridYheight);
			py2 = QPointF(rect().width()-m_panelRMargin,gridYheight);
			painter.drawLine(py1,py2);
		}
	}
	
	// log transform?
	
	// draw color ticks
	
	float xposs1,yposs1,xposs2,yposs2,xposs3,yposs3;
	for(int d=0;d<m_tfColorTick.size();++d)
	{
		xposs1 = m_panelLMargin + m_tfColorTick[d].m_resX * m_tfRes2PtFactor;
		yposs1 = m_panelUMargin + m_panelHeight;
		xposs2 = m_panelLMargin + m_tfColorTick[d].m_resX * m_tfRes2PtFactor - 10;
		yposs2 = m_panelUMargin + m_panelHeight + m_colorTickHeight;
		xposs3 = m_panelLMargin + m_tfColorTick[d].m_resX * m_tfRes2PtFactor + 10;
		yposs3 = m_panelUMargin + m_panelHeight + m_colorTickHeight;
		QPolygon	tri;
		tri << QPoint(xposs1,yposs1) << QPoint(xposs2,yposs2) << QPoint(xposs3,yposs3);
		QBrush		brush2(m_tfColorTick[d].m_color);
		painter.setPen(pen2);
		painter.setBrush(brush2);
		painter.drawPolygon(tri);		
	}
	// draw selected tick
	if(m_clickedTicks >= 0 && m_clickedTicks<m_tfColorTick.size())
	{
		painter.setPen(pen3);
		xposs1 = m_panelLMargin + m_tfColorTick[m_clickedTicks].m_resX * m_tfRes2PtFactor;
		yposs1 = m_panelUMargin + m_panelHeight;
		xposs2 = m_panelLMargin + m_tfColorTick[m_clickedTicks].m_resX * m_tfRes2PtFactor - 10;
		yposs2 = m_panelUMargin + m_panelHeight + m_colorTickHeight;
		xposs3 = m_panelLMargin + m_tfColorTick[m_clickedTicks].m_resX * m_tfRes2PtFactor + 10;
		yposs3 = m_panelUMargin + m_panelHeight + m_colorTickHeight;	
		QPolygon	tri;
		tri << QPoint(xposs1,yposs1) << QPoint(xposs2,yposs2) << QPoint(xposs3,yposs3);
		QBrush		brusht(m_tfColorTick[m_clickedTicks].m_color);
		painter.setBrush(brusht);
		painter.drawPolygon(tri);
	}
	// vert transform string
	if(m_vertStringNeedUpdate)
	{
		painter.setPen(pen2);
		QPoint pts = mapFromGlobal(QCursor::pos());
		QPoint	pt = QPoint(m_panelLMargin,pts.y());//m_panelLMargin,yyy);//m_panelUMargin+0.5*m_panelHeight);// QCursor::pos();
		painter.drawText(pt, m_vertTranPercetangeString);
		m_vertStringNeedUpdate = false;
	}
	// draw object control node
	if(m_gaussianObjectArray.size() != 0)
	{
		for(int x=0;x<m_gaussianObjectArray.size();++x)
		{
			painter.setBrush(Qt::green);
			if(x == m_clickedObjectControlBox)
				painter.setPen(pen3);
			else
				painter.setPen(pen1);
			xposs = m_panelLMargin + m_gaussianObjectArray[x].m_mean * m_panelWidth - 7;
			yposs = m_panelUMargin + m_panelHeight - 14;
			
			painter.drawRect(xposs,yposs,14,14);
			
			painter.setBrush(Qt::red);
			xposs = m_panelLMargin + m_gaussianObjectArray[x].m_mean * m_panelWidth;
			yposs = m_panelUMargin + m_panelHeight - 14;
			
			painter.drawRect(xposs,yposs,7,14);
		}
	}
}
void QTFPanel::resizeEvent(QResizeEvent *event)
{
	m_panelWidth	= rect().width() - m_panelLMargin - m_panelRMargin;
	m_panelHeight	= rect().height() - m_panelUMargin - m_panelDMargin;
	m_panelArea		= QRect(m_panelLMargin,m_panelUMargin,m_panelWidth,m_panelHeight);
	m_colorTickArea	= QRect(m_panelLMargin,m_panelUMargin+m_panelHeight,m_panelWidth,m_colorTickHeight);

	m_tfRes2PtFactor	= (float)m_panelWidth/(m_tfResolution - 1);
	m_tfPt2ResFactor	= 1.0f/m_tfRes2PtFactor;
	
	m_vertTranSlider->setGeometry(0,0,m_panelLMargin,(m_panelUMargin+m_panelHeight)/2);
	m_functionButton->setGeometry(2,m_panelUMargin+(m_panelHeight/2)+2,m_buttonSize.width(),m_buttonSize.height());
	m_settingButton->setGeometry(2,m_panelUMargin+(m_panelHeight/2)+2+m_buttonSize.height()+1,m_buttonSize.width(),m_buttonSize.height());
	
	QTFAbstractPanel::resizeEvent(event);
}
void QTFPanel::updatePanelImage()
{
	QPainter painter(m_panelImage);
	m_panelImage->fill(qRgb(255, 255, 255));
	
	QPen pen1(Qt::black, 1);
	painter.setPen(pen1);	
	QBrush	brush1(QColor(220,220,220,255));
	painter.setBrush(brush1);
	
	painter.drawRect(m_colorTickArea);//m_panelLMargin,m_panelUMargin,m_panelWidth,m_panelHeight);

	QLinearGradient linearGrad(m_panelLMargin,m_panelUMargin+0.5*m_panelHeight,
							   rect().width()-m_panelRMargin,m_panelUMargin+0.5*m_panelHeight);
	for(int x=0;x<m_tfColorTick.size();++x)
	{
		float res = (m_tfColorTick[x].m_resX)/m_tfResolution;
		linearGrad.setColorAt(res,m_tfColorTick[x].m_color);
		//qDebug("%f", m_tfColorTick[x].m_resX);
	}
	painter.fillRect(m_panelArea,linearGrad);
}
void QTFPanel::mousePressEvent(QMouseEvent *event)
{
	if(event->button() == Qt::LeftButton && event->button() == Qt::RightButton)
	{
		m_isLeftClick = false;
		m_isRightClick= false;
		m_ifOnDrawing = false;
	}
	if(event->button() == Qt::LeftButton && ((m_clickedObjectControlBox = clickOnObjctControlBox((QPoint&)event->pos(),m_objectControlBoxSide)) != -1))
	{
		m_isLeftClick = true;
		m_ifOnMovingObjectControlBox = true;
		m_nowPoint = event->pos();
		m_lastPoint = m_nowPoint;
		updateTFColorMap();
		repaint();
	}
	else if(event->button() == Qt::RightButton && ((m_clickedObjectControlBox = clickOnObjctControlBox((QPoint&)event->pos())) != -1))
	{
		m_isRightClick = true;
		m_gaussianObjectArray.remove(m_clickedObjectControlBox);
		m_clickedObjectControlBox = -1;
		m_nowPoint = event->pos();
		m_lastPoint = m_nowPoint;
		updateTFColorMap();
		repaint();
	}
	else if(event->button() == Qt::LeftButton && m_panelArea.contains(event->pos()))
	{
		m_clickedTicks = -1;
		m_isLeftClick = true;
		m_nowPoint = event->pos();

		m_nowResIndex = (m_nowPoint.rx() - m_panelLMargin) * m_tfPt2ResFactor;
		
		int vertSliderValue = m_vertTranSlider->value();
		float lowerPart = (float)vertSliderValue/m_vertTranSliderRange;
		float upperPart = 1.0f - lowerPart;		
		
		float yval;
		float yheight = (float)(m_panelHeight - (m_nowPoint.ry() - m_panelUMargin));
		float halfHeight = 0.5 * m_panelHeight;
		if(yheight <= halfHeight)
		{yval = (yheight/halfHeight)*lowerPart;}
		else
		{yval = ((yheight - halfHeight)/halfHeight) * upperPart + lowerPart;}
		
	//	float yval = (float)(m_panelHeight - (m_nowPoint.ry() - m_panelUMargin))/m_panelHeight;
		m_tfDrawArray[m_nowResIndex] = yval;
		
		m_lastPoint = m_nowPoint;
		m_lastResIndex = m_nowResIndex;
		m_ifOnDrawing = true;
		updateTFColorMap();
		repaint();
	}
	else if(event->button() == Qt::RightButton && m_panelArea.contains(event->pos()))
	{
		m_isRightClick = true;
		m_nowPoint = event->pos();
		
		m_nowResIndex = (m_nowPoint.rx() - m_panelLMargin) * m_tfPt2ResFactor; 
		m_tfDrawArray[m_nowResIndex] = 0.0f;

		m_lastPoint = m_nowPoint;	
		m_lastResIndex = m_nowResIndex;
		m_ifOnDrawing = true;
		updateTFColorMap();
		repaint();
	}	
	else if(event->button() == Qt::LeftButton && 
			(m_colorTickArea.contains(event->pos()) ||
			(m_clickedTicks = clickOnTicks((QPoint&)event->pos())) != -1))
	{
		m_isLeftClick = true;
		QPoint tp = event->pos();
		
		if((m_clickedTicks = clickOnTicks(tp)) == -1)
		{
			int tickResIndex = (tp.rx() - m_panelLMargin) * m_tfPt2ResFactor;
			if(tickResIndex < 0) tickResIndex = 0;
			else if(tickResIndex > m_tfResolution) tickResIndex = m_tfResolution;
			
			QColor tc = QColor::fromRgb(m_panelImage->pixel(tp.x(),m_panelUMargin+0.5*m_panelHeight));
			TFColorTick	temp(tickResIndex,tc);
			m_tfColorTick.append(temp);
			m_clickedTicks = m_tfColorTick.size()-1;
		}
		else  // click an existed tick, set color to colorpicker
 		{
			m_pTFEditor->getColorPicker()->setQColor(m_tfColorTick[m_clickedTicks].m_color);
		}
		m_ifOnDrawColorTick = true;
		updatePanelImage();
		updateTFColorMap();
		repaint();
	}
	else if(event->button() == Qt::RightButton && 
			(m_colorTickArea.contains(event->pos()) ||
			(m_clickedTicks = clickOnTicks((QPoint&)event->pos())) != -1))
	{
		m_isRightClick = true;
		QPoint tp = event->pos();
		
		if(m_tfColorTick.size() > 2)
		{
			m_clickedTicks = clickOnTicks(tp);
			if((m_clickedTicks >= 0) && (m_clickedTicks<(m_tfColorTick.size()))) // exclude empty space (-1)
			{
				m_tfColorTick.remove(m_clickedTicks);
				m_clickedTicks = -1;
				updatePanelImage();
				updateTFColorMap();
				repaint();
			}
		}
	}
}
void QTFPanel::updateTFColorMap()
{
	QColor tc;
	int colorPosx;
	float alphaPosyIdx = m_tfResolution/m_tfColorMapResoultion;
	for(int x=0;x<m_tfColorMapResoultion;++x)
	{
		colorPosx = ((x + 0.5f)/(float) (m_tfColorMapResoultion)) * (m_panelWidth - m_panelLMargin - m_panelRMargin - 1);
		tc = QColor::fromRgb(m_panelImage->pixel(m_panelLMargin+colorPosx,m_panelUMargin+m_panelHeight-5));
		//alphaPosyIdx = colorPosx * m_tfPt2ResFactor;
		m_tfColorMap[4*x] = (float)tc.redF();
		m_tfColorMap[4*x+1] = (float)tc.greenF();
		m_tfColorMap[4*x+2] = (float)tc.blueF();
		m_tfColorMap[4*x+3] = alphaValue((int)(alphaPosyIdx*x));
	}
// 	cout << m_tfColorMap[4*1023 + 3] << endl;
// 	cout << m_tfColorMap[4*1022 + 3] << endl;
// 	cout << m_tfColorMap[4*1021 + 3] << endl;
// 	cout << alphaPosyIdx << endl;
	emit tfColorMapChange();
}
void QTFPanel::mouseDoubleClickEvent(QMouseEvent *event)
{
	if(event->button() == Qt::LeftButton && m_colorTickArea.contains(event->pos()))
	{
		m_isLeftClick = true;
		m_tfColorTick[m_clickedTicks].m_color = m_pTFEditor->getColorPicker()->getQColor();
		m_ifOnDrawColorTick = true;
		updatePanelImage();
		updateTFColorMap();
		repaint();
	}
}
int	QTFPanel::clickOnTicks(QPoint	&pt)
{
	float xposs1,yposs1,xposs2,yposs2,xposs3,yposs3;
	for(int d=0;d<m_tfColorTick.size();++d)
	{
		xposs1 = m_panelLMargin + m_tfColorTick[d].m_resX * m_tfRes2PtFactor;
		yposs1 = m_panelUMargin + m_panelHeight;
		xposs2 = m_panelLMargin + m_tfColorTick[d].m_resX * m_tfRes2PtFactor - 10;
		yposs2 = m_panelUMargin + m_panelHeight + m_colorTickHeight;
		xposs3 = m_panelLMargin + m_tfColorTick[d].m_resX * m_tfRes2PtFactor + 10;
		yposs3 = m_panelUMargin + m_panelHeight + m_colorTickHeight;
		QPolygon	tri;
		tri << QPoint(xposs1,yposs1) << QPoint(xposs2,yposs2) << QPoint(xposs3,yposs3);
		if(tri.containsPoint(pt, Qt::OddEvenFill))
			return d;
	}	
	return -1;
}
int QTFPanel::clickOnObjctControlBox(QPoint	&pt)
{
	if(m_gaussianObjectArray.size() != 0)
	{
		float xposs,yposs;
		for(int x=0;x<m_gaussianObjectArray.size();++x)
		{
			xposs = m_panelLMargin + m_gaussianObjectArray[x].m_mean * m_panelWidth - 7;
			yposs = m_panelUMargin + m_panelHeight - 14;
			QRect temp(xposs,yposs,14,14);
			if(temp.contains(pt))
			{
				return x;
			}
		}
	}
	return -1;
}
int QTFPanel::clickOnObjctControlBox(QPoint	&pt,int &side)
{
	if(m_gaussianObjectArray.size() != 0)
	{
		float xposs,yposs;
		for(int x=0;x<m_gaussianObjectArray.size();++x)
		{
			xposs = m_panelLMargin + m_gaussianObjectArray[x].m_mean * m_panelWidth - 7;
			yposs = m_panelUMargin + m_panelHeight - 14;
			QRect temp1(xposs,yposs,14,14);
			if(temp1.contains(pt))
			{
				xposs = m_panelLMargin + m_gaussianObjectArray[x].m_mean * m_panelWidth;
				QRect temp2(xposs,yposs,7,14);
				if(temp2.contains(pt))
					side = 1;  // right
				else 
					side = 2;  // left
				return x;
			}
		}
	}
	return -1;	
}
void QTFPanel::mouseMoveEvent(QMouseEvent *event)
{
	if(m_isLeftClick && m_ifOnMovingObjectControlBox)
	{
		m_nowPoint = event->pos();
		float xposs = (float)(m_nowPoint.rx() - m_panelLMargin)/m_panelWidth;
		if(xposs < 0.0f) xposs = 0.0f;
		else if(xposs > 1.0f) xposs = 1.0f;
		
		float ypossnow = (float)(m_panelUMargin+m_panelHeight-(m_nowPoint.ry() - m_panelUMargin)) / m_panelHeight;
		float ypossold = (float)(m_panelUMargin+m_panelHeight-(m_lastPoint.ry() - m_panelUMargin)) / m_panelHeight;
		float diffy = ypossnow - ypossold;
		m_gaussianObjectArray[m_clickedObjectControlBox].m_mean = xposs;
			
		if(m_objectControlBoxSide==2) // left 
		{			
			m_gaussianObjectArray[m_clickedObjectControlBox].m_heightFactor += 0.1*diffy;
			if(m_gaussianObjectArray[m_clickedObjectControlBox].m_heightFactor < 0.0f) 
				m_gaussianObjectArray[m_clickedObjectControlBox].m_heightFactor = 0.0f;
			else if(m_gaussianObjectArray[m_clickedObjectControlBox].m_heightFactor > 1.0f) 
				m_gaussianObjectArray[m_clickedObjectControlBox].m_heightFactor = 1.0f;
		}
		else if((m_objectControlBoxSide==1) && (m_ifCTRLPressed == false))// right side
		{
			m_gaussianObjectArray[m_clickedObjectControlBox].m_sigma += 0.1*diffy;
			if(m_gaussianObjectArray[m_clickedObjectControlBox].m_sigma <= 0.0f) 
				m_gaussianObjectArray[m_clickedObjectControlBox].m_sigma = 1e-3;
		}
//		else if((m_objectControlBoxSide==1) && (m_ifCTRLPressed == true))// right side
//		{
//		}
		m_gaussianObjectArray[m_clickedObjectControlBox].update();
		m_lastPoint = m_nowPoint;
		updateTFColorMap();
		repaint();
	}
	else if(m_isLeftClick && m_ifOnDrawing)
	{
		m_nowPoint = event->pos();
		m_nowResIndex = (m_nowPoint.rx() - m_panelLMargin) * m_tfPt2ResFactor;
		if(m_nowResIndex < 0) m_nowResIndex = 0;
		else if(m_nowResIndex >= m_tfResolution) m_nowResIndex = m_tfResolution-1;
		
		int vertSliderValue = m_vertTranSlider->value();
		float lowerPart = (float)vertSliderValue/m_vertTranSliderRange;
		float upperPart = 1.0f - lowerPart;		
		
		float yval;
		float yheight = (float)(m_panelHeight - (m_nowPoint.ry() - m_panelUMargin));
		float halfHeight = 0.5 * m_panelHeight;
		if(yheight <= halfHeight)
		{yval = (yheight/halfHeight)*lowerPart;}
		else
		{yval = ((yheight - halfHeight)/halfHeight) * upperPart + lowerPart;}
		
		if(yval > 1.0f) yval = 1.0f;
		else if(yval < 0.0f) yval = 0.0f;
		
		m_tfDrawArray[m_nowResIndex] = yval;
		m_lastPoint = m_nowPoint;	
		if(abs(m_nowResIndex - m_lastResIndex) > 1)
		{interpolateResPoint();	}
		
		m_lastResIndex = m_nowResIndex;
		updateTFColorMap();
		repaint();
	}
	else if(m_isRightClick && m_ifOnDrawing)
	{
		m_nowPoint = event->pos();
		m_nowResIndex = (m_lastPoint.rx() - m_panelLMargin) * m_tfPt2ResFactor; 
		if(m_nowResIndex < 0) m_nowResIndex = 0;
		else if(m_nowResIndex >= m_tfResolution) m_nowResIndex = m_tfResolution-1;	
		m_tfDrawArray[m_nowResIndex] = 0.0f;
		m_lastPoint = m_nowPoint;	
		if(abs(m_nowResIndex - m_lastResIndex) > 1)
		{interpolateResPoint();	}
		m_lastResIndex = m_nowResIndex;
		updateTFColorMap();
		repaint();
		//	m_optionMenu->exec(QCursor::pos());
	}
	else if(m_isLeftClick && m_ifOnDrawColorTick)
	{
		QPoint	pt = event->pos();
		int xResPos = (pt.rx() - m_panelLMargin) * m_tfPt2ResFactor;  
		if(xResPos < 0) xResPos = 0;
		else if(xResPos > m_tfResolution) xResPos = m_tfResolution;
		m_tfColorTick[m_clickedTicks].m_resX = xResPos;
		
		updatePanelImage();
		updateTFColorMap();
		repaint();
	}
	if(m_instant)
		emit tfChanged(m_tfColorMap);
}
void QTFPanel::mouseReleaseEvent(QMouseEvent* event)
{
	if(event->button() == Qt::LeftButton && m_isLeftClick)
		m_isLeftClick = false;
	if(event->button() == Qt::RightButton && m_isRightClick)
		m_isRightClick = false;
	m_ifOnDrawing = false;
	if(m_ifOnDrawColorTick)
	{
		m_ifOnDrawColorTick = false;
	}
	m_ifOnMovingObjectControlBox = false;
	generateZeroRanges();
	emit tfChanged(m_tfColorMap);
}

void QTFPanel::generateZeroRanges() {
	m_zeroRangesArray.clear();
	float start = -1;
	for(int i = 0; i < m_tfResolution; i++) {
		if(alphaValue(i) < 1e-3) {
			start = i/(m_tfResolution - 1);
			i++;
			for(; i < m_tfResolution; i++) {
				if(alphaValue(i) > 1e-3) {
					m_zeroRangesArray.append(ZeroRange(start, (i-1)/(m_tfResolution - 1)));
					start = -1;
					break;
				}
			}
		}
	}
	if(start != -1) {
		m_zeroRangesArray.append(ZeroRange(start, 1.0f));
	}
// 	for(int i = 0; i < m_zeroRangesArray.size(); i++) {
// 		cout << m_zeroRangesArray[i].start << " " << m_zeroRangesArray[i].end << endl;
// 	}
}

float QTFPanel::alphaValue(int x) {
	if(x < 0 || x >= m_tfResolution)
		return 0;
	float alpha;
	alpha = m_tfDrawArray[x];
	if(m_combineMode == 0) { //or
		for(int i = 0; i < m_gaussianObjectArray.size(); i++) {
			alpha = alpha > m_gaussianObjectArray[i].m_distribution[x] ?
					alpha : m_gaussianObjectArray[i].m_distribution[x];
		} 
	} else if(m_combineMode == 1) { //and
		for(int i = 0; i < m_gaussianObjectArray.size(); i++) {
			alpha += m_gaussianObjectArray[i].m_distribution[x];
		}
	}
	alpha = alpha > 1.f ? 1.f : alpha < 1e-10 ? 0 : alpha;
	return alpha;
}

/*
void QTFPanel::keyPressEvent(QKeyEvent *event)
{
	if(event->key() == Qt::Key_Control)
		m_ifCTRLPressed = true;
	if(event->key() == Qt::Key_Shift)
		m_ifSHIFTPressed = true;
}
void QTFPanel::keyReleaseEvent(QKeyEvent *event)
{
	if(event->key() == Qt::Key_Control)
		m_ifCTRLPressed = false;
	if(event->key() == Qt::Key_Shift)
		m_ifSHIFTPressed = false;
}
*/
void QTFPanel::interpolateResPoint()
{
	int		resIdx1,resIdx2;
	float	resIdx1y,resIdx2y;
	
	if(m_nowResIndex > m_lastResIndex)
	{
		resIdx1 = m_lastResIndex;
		resIdx2 = m_nowResIndex;
	}
	else
	{
		resIdx2 = m_lastResIndex;
		resIdx1 = m_nowResIndex;
	}
	resIdx1y = m_tfDrawArray[resIdx1];
	resIdx2y = m_tfDrawArray[resIdx2];
	int nosPt = resIdx2 - resIdx1 - 1;
	float slope = (resIdx2y-resIdx1y)/(resIdx2-resIdx1);
	
	for(int x=1;x<=nosPt;++x)
	{
		float val = resIdx1y + slope * x;
		m_tfDrawArray[resIdx1+x] = val;
	}
}


void QTFPanel::changeSelectedTickColor(QColor &cr)
{
	if(m_clickedTicks >= 0 && m_clickedTicks<m_tfColorTick.size())
	{
		m_tfColorTick[m_clickedTicks].m_color = cr;
		updatePanelImage();
		updateTFColorMap();
		repaint();
		if(m_instant)
			emit tfChanged(m_tfColorMap);
	}
}
void QTFPanel::vertTranSliderChange(int value)
{
//	int minn = m_vertTranSlider->minimum();
//	int maxx = m_vertTranSlider->maximum();
//	int vall = value;
	
	//float perct = (float)vall/(float)(maxx-minn+1);
	m_vertTranPercetangeString = QString("%1").arg(value);
	m_vertStringNeedUpdate = true;
	repaint();
}
void QTFPanel::functionButtonPressed()
{
	//static int counter = 0;
	
	GaussianObject temp(0.5,0.1,0.1,m_tfResolution);
	temp.update();
	m_gaussianObjectArray << temp;
	updatePanelImage();
	updateTFColorMap();
	generateZeroRanges();
	repaint();
	emit tfChanged(m_tfColorMap);
	//counter++;
}
//double QTFPanel::gaussianGen(double x,double mean,double sigma)
//{
//	double val = 1.0/(sigma*sqrt(2.0*3.1415926)) * exp(-(x-mean)*(x-mean)/(2.0*sigma*sigma));
//	return val;
//}
void QTFPanel::settingButtonPressed()
{
	m_settingMenu->exec(QCursor::pos());
}
void QTFPanel::changeBM2None()
{
	changeBM2NoneAct->setChecked(true);
	changeBM2DotLineAct->setChecked(false);		
	m_backgroundMesh = 0;
	//updatePanelImage();
	repaint();
}
void QTFPanel::changeBM2DotLine()
{
	changeBM2NoneAct->setChecked(false);
	changeBM2DotLineAct->setChecked(true);	
	m_backgroundMesh = 1;
	//updatePanelImage();
	repaint();
}
void QTFPanel::changeCombine2Or() {
	changeCombine2OrAct->setChecked(true);
	changeCombine2AndAct->setChecked(false);
	m_combineMode = 0;
	updateTFColorMap();
	repaint();
}
void QTFPanel::changeCombine2And() {
	changeCombine2OrAct->setChecked(false);
	changeCombine2AndAct->setChecked(true);
	m_combineMode = 1;
	updateTFColorMap();
	repaint();
}

void QTFPanel::saveFile() {
	QString filename = QFileDialog::getSaveFileName(this, tr("Save Settings"), ".", tr("TFEditor files (*.tfe);;All files (*.*)"));
	if(!filename.isEmpty()) {
		if(!filename.contains(QString(".")))
			filename += ".tfe";
		QFile file(filename);
		if(!file.open(QIODevice::WriteOnly))
			return;
		saveFile(file);
		file.close();
	}
}
void QTFPanel::openFile() {
	QString filename = QFileDialog::getOpenFileName(this, tr("Load Saved Settings"), ".", tr("TFEditor files (*.tfe);;All files (*.*)"));
	if(!filename.isEmpty()) {
		QFile file(filename);
		if(!file.open(QIODevice::ReadOnly))
			return;
		openFile(file);
		file.close();
		emit tfChanged(m_tfColorMap);
	}
}

QFile& QTFPanel::openFile(QFile& file) {
	if(!file.isReadable())
		return file;
	file.read((char*)&m_tfResolution, 4);
	delete [] m_tfDrawArray;
	m_tfDrawArray = new float[(int)m_tfResolution];
	file.read((char*)m_tfDrawArray, (int)m_tfResolution*4);
	int size;
	file.read((char*)&size, 4);
	m_gaussianObjectArray.clear();
	double t[3];
	for(int i = 0; i < size; i++) {
		file.read((char*)t, 24);
		GaussianObject obj(t[0], t[1], t[2], m_tfResolution);
		obj.update();
		m_gaussianObjectArray.push_back(obj);
	}
	file.read((char*)&size, 4);
	float resX;
	m_tfColorTick.clear();
	QColor c;
	for(int i = 0; i < size; i++) {
		file.read((char*)&resX, 4);
		file.read((char*)t, 24);
		c.setRgbF(t[0], t[1], t[2]);
		TFColorTick tick(resX, c);
		m_tfColorTick.push_back(tick);
	}
	file.read((char*)&m_combineMode, 4);
	if(m_combineMode == 0) {
		changeCombine2OrAct->setChecked(true);
		changeCombine2AndAct->setChecked(false);
	} else if(m_combineMode == 1) {
		changeCombine2OrAct->setChecked(false);
		changeCombine2AndAct->setChecked(true);
	}
	file.read((char*)&size, 4);
	m_vertTranSlider->setValue(size);
	file.read((char*)&m_backgroundMesh, 4);
	file.read((char*)t, 24);
	c.setRgbF(t[0], t[1], t[2]);
	m_pTFEditor->getColorMap()->changeBGColor(c);
	updatePanelImage();
	updateTFColorMap();
	repaint();
	return file;
}
QFile& QTFPanel::saveFile(QFile& file) {
	if(!file.isWritable())
		return file;
	file.write((char*)&m_tfResolution, 4);
	file.write((char*)m_tfDrawArray, m_tfResolution*4);
	int size = m_gaussianObjectArray.size();
	file.write((char*)&size, 4);
	for(int i = 0; i < size; i++) {
		file.write((char*)&(m_gaussianObjectArray[i].m_mean), 8);
		file.write((char*)&(m_gaussianObjectArray[i].m_sigma), 8);
		file.write((char*)&(m_gaussianObjectArray[i].m_heightFactor), 8);
	}
	size = m_tfColorTick.size();
	file.write((char*)&size, 4);
	double t[3];
	for(int i = 0; i < size; i++) {
		file.write((char*)&(m_tfColorTick[i].m_resX), 4);
		m_tfColorTick[i].m_color.getRgbF(t, t+1, t+2);
		file.write((char*)t, 24);
	}
	file.write((char*)&m_combineMode, 4);
	size = m_vertTranSlider->value();
	file.write((char*)&size, 4);
	file.write((char*)&m_backgroundMesh, 4);
	m_pTFEditor->getColorMap()->getBackgroundColor().getRgbF(t, t+1, t+2);
	file.write((char*)t, 24);
	return file;
}

void QTFPanel::toggleInstant() {
	m_instant = !m_instant;
	toggleInstantAct->setChecked(m_instant);
}
